#ifndef _UIC_WIDGETS_H
#define _UIC_WIDGETS_H

namespace uic
{

struct font_metric
    {
    double size;  // the size that was used to figure the metrics

    double y_origin;     // amount to subtract from y2 to reach the origin line
    double height;       // maximum height found
    double advance;      // maximum x advance found
    double num_advance;  // largest x advance found for numeric glyphs
    char widest_digit;   // widest numeric digit
    double timesep_advance;  // x advance of the time separator char
    };

class w_Button : public Widget
    {
  protected:
    bool pressed,
         mouseover;
   w_Button () : pressed(false), mouseover(false) {}
  public:
//    static Color bc,  // button color (background)
//                 bcf, bcfb, bcfd;  // foreground, bright, dark

    double draw_button(CairoUI *ui, cairo_t *cr, double *x1, double *y1,
                                                 double *x2, double *y2);
    static void set_button_gradient(cairo_pattern_t *pattern, CairoUI *ui);

    void check_size(CairoUI *ui);
    virtual bool button_press(CairoUI *ui, GenericEvent *ev);
    virtual bool pointer_motion(CairoUI *ui, GenericEvent *ev);
    virtual void pointer_leave(CairoUI *ui);
    };

class w_Stop : public w_Button
    {
  public:
    bool button_release(CairoUI *ui, GenericEvent *ev, bool inside);
    void draw(CairoUI *ui, cairo_t *cr);
    };

class w_Play : public w_Button
    {
  public:
    bool button_release(CairoUI *ui, GenericEvent *ev, bool inside);
    void draw(CairoUI *ui, cairo_t *cr);
    };

class w_Pause : public w_Button
    {
  public:
    bool button_release(CairoUI *ui, GenericEvent *ev, bool inside);
    void draw(CairoUI *ui, cairo_t *cr);
    };

class w_PlayPause : public w_Button
    {
  public:
    bool button_release(CairoUI *ui, GenericEvent *ev, bool inside);
    void draw(CairoUI *ui, cairo_t *cr);
    void event(CairoUI *ui, Event ev);
    };

class w_Previous : public w_Button
    {
  public:
    bool button_release(CairoUI *ui, GenericEvent *ev, bool inside);
    void draw(CairoUI *ui, cairo_t *cr);
    };

class w_Next : public w_Button
    {
  public:
    bool button_release(CairoUI *ui, GenericEvent *ev, bool inside);
    void draw(CairoUI *ui, cairo_t *cr);
    };

class w_Volume : public Widget
    {
  public:
    void check_size(CairoUI *ui);
    bool button_press(CairoUI *ui, GenericEvent *ev);
    bool button_release(CairoUI *ui, GenericEvent *ev, bool inside);
    void draw(CairoUI *ui, cairo_t *cr);
    };

#if 0
class w_PreviousArrow : public Widget
    {
  public:
    bool button_press(CairoUI *ui, GenericEvent *ev);
    void draw(CairoUI *ui);
    bool pointer_motion(CairoUI *ui, GenericEvent *ev);
    void pointer_leave(CairoUI *ui);
    }

class w_NextArrow : public Widget
    {
  public:
    bool button_press(CairoUI *ui, GenericEvent *ev);
    void draw(CairoUI *ui);
    bool pointer_motion(CairoUI *ui, GenericEvent *ev);
    void pointer_leave(CairoUI *ui);
    }
#endif

class w_Text : public Widget
    {
  public:
    bool set_justify (Justify just) { justify = just; return true; }
    char *slash_separator;
    bool truncate_end;

  protected:
    Justify justify;
    struct font_metric fm;
    void draw_text(CairoUI *ui, cairo_t *cr,
                   const char *text, const char *separator=0);

    bool reduce_font_for_width(cairo_t *cairo, double *font_size,
                               const char *str, double min_size);
    bool text_center_on_sep(CairoUI *ui, cairo_t *cr,
                            const char *text, const char *sep);
    void justify_text(CairoUI *ui, cairo_t *cr, const char *text);
    void text_truncate(CairoUI *ui, cairo_t *cr, const char *text,
                       const cairo_text_extents_t *ext);
//    bool text_status(CairoUI *ui, cairo_t *cr, const char *text);
    };

class w_Position : public w_Text
    {
    void determine_font_size(cairo_t *cairo);
  public:
    w_Position();
    void configure(CairoUI *ui);
    void draw(CairoUI *ui, cairo_t *cr);
    void event(CairoUI *ui, Event ev);
    };

class w_TimeDisplay : public w_Text
    {
    UI::TimeDisplay display_type;
    char *showing_text;
    char *showing_sep;
    void determine_font_size(CairoUI *ui, cairo_t *cr);
    void show_text(const char *text, time_t seconds)
        { show_text(text, 0, seconds); }
    void show_text(const char *text, const char *separator, time_t seconds);
  public:

    w_TimeDisplay();
    void timer_event(CairoUI *ui);
    void event(CairoUI *ui, Event ev);
    void event(CairoUI *ui, WidgetEvent event);
    void configure(CairoUI *ui);
    void draw(CairoUI *ui, cairo_t *cr);
    bool button_press(CairoUI *ui, GenericEvent *ev);

    };

class w_ProgressBar : public Widget
    {
    bool   pressed;
    bool   mouseover;
    bool   vertical;
    bool   indicator_needed;
    double left, right,
           top, bottom;
    double linewidth;
    int    selected;

  public:
    w_ProgressBar () : pressed(false), mouseover(false),
                       indicator_needed(false) {}

    void configure(CairoUI *ui);
    void timer_event(CairoUI *ui);
    void event(CairoUI *ui, Event ev);

    void draw(CairoUI *ui, cairo_t *cr);
    bool button_press(CairoUI *ui, GenericEvent *ev);
    bool button_release(CairoUI *ui, GenericEvent *ev, bool inside);
    bool pointer_motion(CairoUI *ui, GenericEvent *ev);
    void pointer_leave(CairoUI *ui);

  protected:
    void redraw_indicator(CairoUI *ui, cairo_t *cr);
    void select(int x, int y);
    unsigned int selected_time();
    };

class w_Icon : public Widget
    {
  public:
    void check_size(CairoUI *ui);
    bool button_press(CairoUI *ui, GenericEvent *ev);
    bool slow_redraw () { return true; }
    void draw(CairoUI *ui, cairo_t *cr);
    };

class w_Canvas : public Widget
    {
  public:
    w_Canvas();
    virtual void draw (CairoUI *ui, cairo_t *cr) { redraw_needed = false; }

  protected:
    virtual void draw_surface(cairo_t *cr, double use_x, double use_y, double scale);
    cairo_surface_t *surface;
    };

class TestCanvas : public w_Canvas
    {
  public:
    bool draw_background(CairoUI *ui, cairo_t *cr,
                         double x1, double y1, double x2, double y2);
    void set_option(const char *str);
    void disable();
    void configure(CairoUI *ui);
    bool is_physical () { return false; }

    TestCanvas();
  protected:
    bool test1, test2;
    cairo_pattern_t *pattern;
    };

#ifdef COVERART
class w_Coverart : public w_Canvas
    {
    string source_hash;
    void set_picture(CairoUI *ui, unsigned char *data, unsigned int length);
    void clear_picture();

  public:
    int  min_size;
    bool minimized;

    w_Coverart();
    ~w_Coverart();

    bool slow_redraw () { return true; }
    void check_size(CairoUI *ui);
    void configure(CairoUI *ui);
    void disable();
    void event(CairoUI *ui, Event ev);
    void event(CairoUI *ui, Event ev, EventData *event_data);
    void draw(CairoUI *ui, cairo_t *cr);
    bool button_press(CairoUI *ui, GenericEvent *ev);
    };
#endif

}
#endif // _UIC_WIDGET_H
